package com.m4f.business.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import com.m4f.business.model.Company;
import com.m4f.business.model.Vote;
import com.m4f.business.persistence.PMF;
import com.m4f.business.service.ifc.IVoteService;
import com.m4f.utils.StackTraceUtil;
import com.m4f.business.service.exception.DuplicatedVoteException;
import com.m4f.business.service.exception.VotesLimitExceedException;

public class VoteService implements IVoteService {
	
	private static final Logger LOGGER = Logger.getLogger(VoteService.class.getName());
	
	@Override
	public void addVote(Vote vote) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			pm.makePersistent(vote);
		} catch(Exception e) {
			LOGGER.severe(StackTraceUtil.getStackTrace(e));
		} finally {
			pm.close();
		}
	}
	
	@Override
	public Integer countVotes(String email) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Vote.class);
		query.setFilter("email == emailParam");
		query.declareParameters("java.lang.String emailParam");
		query.setResult("count(email)");
		Integer count = 0;
		try {
			 count = (Integer)query.execute(email);
	    } catch(Exception e) {
	    	LOGGER.severe(StackTraceUtil.getStackTrace(e));
	    } finally {
	        query.closeAll();
	        pm.close();
	    }
		return count;
	}
		
	
	public Map<String, List<Vote>> getVotesIndexedByEmail(Long init, 
			Long end ) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Vote.class);
		query.setRange(init, end);
		query.setOrdering("email asc");
		List<Vote> results = new ArrayList<Vote>();
		try {
	        results.addAll((List<Vote>)query.execute());
	    } catch(Exception e) {
	    	LOGGER.severe(StackTraceUtil.getStackTrace(e));
	    } finally {
	        query.closeAll();
	        pm.close();
	    }
	    return this.groupByEmail(results);
	}
	
	public List<Vote> getAllVotes() {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Vote.class);
		List<Vote> results = new ArrayList<Vote>();
		try {
			results.addAll((List<Vote>)query.execute());
	    } catch(Exception e) {
	    	LOGGER.severe(StackTraceUtil.getStackTrace(e));
	    } finally {
	        query.closeAll();
	        pm.close();
	    }
	    return results;
	}
	
	public List<Vote> getVotesByCompany(Long  companyId) {
		List<Vote> results = new ArrayList<Vote>();
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Vote.class);
		query.setFilter("companyId == companyIdParam");
		query.declareParameters("java.lang.Long companyIdParam");
		try {
	        results.addAll((List<Vote>)query.execute(companyId));
	    } catch(Exception e) {
	    	LOGGER.severe(StackTraceUtil.getStackTrace(e));
	    } finally {
	        query.closeAll();
	        pm.close();
	    }
		return results;
	}
	
	public boolean removeVotes(String email) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Vote.class);
		List<Vote> results = new ArrayList<Vote>();
		query.setFilter("email == emailParam");
		query.declareParameters("java.lang.String emailParam");
		try { 
			results.addAll((List<Vote>)query.execute(email));
			for(Vote vote : results) {
				pm.deletePersistent(vote);
			}
	    } catch(Exception e) {
	    	LOGGER.severe(StackTraceUtil.getStackTrace(e));
	    	return false;
	    } finally {
	        query.closeAll();
	        pm.close();
	    }
	    return true;
	}
	
	/*********************************************************************
	 * 			PRIVATE METHODS, TO CHANGE :-).
	 *********************************************************************/
	
	
	/**
	 * 
	 * @param initialList
	 * @return
	 */
	
	private Map<String, List<Vote>> groupByEmail(List<Vote> initialList) {
		Map<String, List<Vote>> groupedVotes = new HashMap<String, List<Vote>>();
		for(Vote vote : initialList) {
			if(!groupedVotes.containsKey(vote.getEmail())) {
				groupedVotes.put(vote.getEmail(), new ArrayList<Vote>());
			}
			groupedVotes.get(vote.getEmail()).add(vote);
		}
		return groupedVotes;
	}
	
}